package com.jysz.certificate.web.action.mf;

import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.jysz.certificate.action.AbstractBaseAction;
import com.jysz.certificate.persistence.enums.mf.BillStatus;
import com.jysz.certificate.persistence.model.mf.Bill;
import com.jysz.certificate.persistence.model.mf.BillApply;
import com.jysz.certificate.persistence.model.mf.BillOption;
import com.jysz.certificate.persistence.model.system.Financial;
import com.jysz.certificate.persistence.model.system.Shop;
import com.jysz.certificate.persistence.model.system.Treaty;
import com.jysz.certificate.service.mf.BillApplyService;
import com.jysz.certificate.service.mf.BillOptionService;
import com.jysz.certificate.service.mf.BillService;
import com.jysz.certificate.service.system.FinancialService;
import com.jysz.certificate.service.system.ShopService;
import com.jysz.certificate.service.system.TreatyService;
import com.jysz.certificate.utils.CommonUtil;
import com.jysz.certificate.utils.DateUtil;
import com.jysz.certificate.utils.PoiUtils;
import com.jysz.webcore.ssh.orm.hibernate.support.Page;

/**
 * 发票申请控制类(申请列表、申请-店)
 * @author xuxiaolong
 */
@Controller
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Namespace("/mf/apply")
public class BillApplyShopAction extends AbstractBaseAction {

	private static final long serialVersionUID = -3011627853588411366L;
	
	@Resource
	private BillApplyService applyService;
	@Resource
	private TreatyService treatyService;
	@Resource
	private BillService billService;
	@Resource
	private BillOptionService optionService;
	@Resource
	private FinancialService financialService;
	@Resource
	private ShopService shopService;
	private BillApply entity;
	private BillApply search;
	private Bill bill;
	private Long id;
	private Long shopId;
	private Long financialId;
	private int operate;
	private List<Object[]> detailData;//发票申请单详情所需列表
	private List<Financial> financials;//允许预收的金融机构
	private List<Financial> financialsQuarter;//允许预收的金融机构
	private List<Financial> financialsHalfYear;//允许预收的金融机构
	private String editData;//存放编辑发票时表格中原有行的数据
	private String newData;//存放编辑发票时表格中新增行的数据
	private String months;//编辑发票时新增的月份
	private String ids;
	private String idmons;
	private Shop shopDTO;
	private String type;
	private String group;
	
	/**
	 * 查询-列表
	 * @return
	 */
	@Action(INDEX)
	public String index(){
		
		setPage(applyService.findPage(search, getCurrentPage(), getPageSize()));
		return INDEX;
	}
	
	//新建发票申请
	@Action(ADD)
	public String add() throws ParseException{
		
		try {
			Object flag=this.getServletContext().getAttribute("MfApplyShopInProgress");//检测是否有正在生成
			if(flag!=null&&flag.toString().equals("1")){
				setFailPopMessage("上一次生成还在进行中，请稍后重试");
			}else{
				this.getServletContext().setAttribute("MfApplyShopInProgress","1");//设置正在生成标识,不允许其他
				entity=applyService.create(getUser());
				if(entity!=null){
					detailData=applyService.view(entity.getId());
					setSuccessPopMessage("已成功生成所有应收管理费");
				}else{
					setFailPopMessage("没有应收管理费");
				}
				setRedirectUrl("index.do?currentPage="+getCurrentPage(),null,search);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			this.getServletContext().removeAttribute("MfApplyShopInProgress");//去掉正在生成标识
		}
		//setPage(applyService.findPage(search, getCurrentPage(), getPageSize()));
		return SHOW_MSG_PAGE;
//		return "billApplyEdit";
	}
	
	//申请-编辑
	@Action(EDIT)
	public String edit(){
		detailData=applyService.view(id,getCurrentPage(), this.getPageSize());
		entity=applyService.find(id);
		financials=applyService.getFins(id);
		Page<Object> page = new Page<Object>();
		page.setTotalCount(applyService.view(id).size());
		page.setPageNo(getCurrentPage());
		page.setPageSize(20);
		this.setPage(page);
		//setPage(applyService.findPage(search, getCurrentPage(), getPageSize()));
		return "billApplyEdit";
	}
	
	//申请-详情
	@Action("view")
	public String view(){
		detailData=applyService.view(id,getCurrentPage(), this.getPageSize());
		entity=applyService.find(id);
		financials=applyService.getFins(id);
		Page<Object> page = new Page<Object>();
		page.setTotalCount(applyService.view(id).size());
		page.setPageNo(getCurrentPage());
		page.setPageSize(20);
		this.setPage(page);
		return "billApplyView";
	}
	
	//导出
	@Action("exportBillShopx")
	public String exportBillShopx(){
		detailData=applyService.view(id);
		financials=applyService.getFins(id);
//		List<BillOption> billOptions = billOptionService.exportBillOptions(id);
		int size=0;
		if(financials!=null)
			size=financials.size();
		String[] headers = new String[5+size];
		String[] columns = new String[5+size];
		headers[0]="店号";
		columns[0]="#st[1]";
		headers[1]="店名";
		columns[1]="#st[2]";
		headers[2]="驻店顾问";
		columns[2]="#cfa.getShopUserNames(#st[0])";
		headers[3]="区域经理";
		columns[3]="#cfa.getAreaManagerNames(#st[0])";
		int rowNum=4;
		for(Financial fin:financials){
			headers[rowNum]=fin.getName();
			columns[rowNum]="#st["+(rowNum-1)+"]";
			rowNum++;
		}
		headers[rowNum]="总计";
		columns[rowNum]="#st["+(rowNum-1)+"]";
		HttpServletResponse response = this.getResponse();
	    response.setContentType("octets/stream");
	    response.addHeader("Content-Disposition","attachment;filename=" + toUtf8Encode("店铺发票明细") + ".xls");
	    OutputStream out = null;
		try {
			out = this.getResponse().getOutputStream();
			Map<String, Object> context = new HashMap<String, Object>();
			context.put("cfa", this);
			PoiUtils.exportExcel("店铺发票明细", headers, columns, detailData, out, null, context,"st");
		} catch (Exception e) {
			LOG.error("导出店铺发票明细出错。。。", e);
		}
		
		return null;
		
	}
	
	//申请-保存
	@Action(UPDATE)
	public String update(){
		BillApply apply= applyService.find(id);
		apply.setApplyNum(entity.getApplyNum());
		updateAloneOpen(apply, ids);
		if(operate==1){
			applyService.submit(apply,CommonUtil.getLongList(ids),CommonUtil.getLongList(idmons));
		}else{
			applyService.save(apply);
		}
		if(shopId!=null){
			return edit();
		}else{
			setSuccessPopMessage("发票申请保存成功");
			setRedirectUrl("index.do?currentPage="+getCurrentPage());
			return SHOW_MSG_PAGE;
		}
		
	}

	public void updateAloneOpen(BillApply apply,String ids){
		if(apply==null)
			return;
		else{// if(CommonUtil.isNotEmpty(ids)||CommonUtil.isNotEmpty(idmons))
			List<Long> list=CommonUtil.getLongList(ids);
			List<Long> listMons=CommonUtil.getLongList(idmons);
			for(Bill bill:apply.getBills()){
				if(list!=null&&list.contains(bill.getId())){
					bill.setAloneOpen(true);
				}else{
					bill.setAloneOpen(false);
				}
				if(listMons!=null&&listMons.contains(bill.getId())){
					bill.setAloneMonth(true);
				}else{
					bill.setAloneMonth(false);
				}
			}
		}
		if(shopId!=null){//新增店铺预收
			Shop shop=shopService.find(shopId);
			Bill bill=new Bill();
			bill.setStatus(BillStatus.TEMPSAVE);
			bill.setPaymentName(shop.getCompany());
			bill.setBillApply(apply);
			bill.setShop(shop);
			bill.setReceivableAmount(0D);
			apply.getBills().add(bill);
		}
	}
	
	//发票-编辑
	@Action("billEdit")
	public String billEdit(){
		bill=billService.find(entity.getId());
		BillApply apply=bill.getBillApply();
		updateAloneOpen(apply, ids);
		applyService.save(apply);
		
		Date d=apply.getApplyDate();
		if(d==null)
			d=apply.getCreatedAt();
		
		//查询看是否有当前月份被之前预收的。也作显示
		List<BillOption> options=applyService.findCurrentMonthAdvance(bill.getShop().getId(),DateUtil.formatDate(d, "yyyy-MM"));
		if(bill.getOptions()!=null&&options!=null){
			for(BillOption bo:options){
				if(!bill.getOptions().contains(bo)){
					bo.setOperate(2);
					bill.getOptions().add(bo);
				}
				
			}
		}
		setRedirectUrl("edit.do?currentPage="+getCurrentPage()+"&id="+apply.getId());
		financials=financialService.findAdvanceByShop(bill.getShop().getId(),"0");
		return "billEdit";
	}
	
		//选择预收金融机构
		@Action("chooseFin")
		public String chooseFin(){
			bill=billService.find(entity.getId());
			
			//月份预收金融机构
			financialsQuarter=financialService.findAdvanceByShop(bill.getShop().getId(),"1");
			financialsHalfYear=financialService.findAdvanceByShop(bill.getShop().getId(),"2");
			return "chooseFin";
		}
		
	//发票-删除发票(店铺)
	@Action("billDel")
	public String billDel(){
		bill=billService.find(entity.getId());
		BillApply apply=bill.getBillApply();
		updateAloneOpen(apply, ids);
		apply.getBills().remove(bill);
		applyService.save(apply);
		//删除 
		billService.del(bill);
	
		detailData=applyService.view(id,getCurrentPage(), this.getPageSize());
		entity=applyService.find(id);
		financials=applyService.getFins(id);
		Page<Object> page = new Page<Object>();
		page.setTotalCount(applyService.view(id).size());
		page.setPageNo(getCurrentPage());
		page.setPageSize(20);
		this.setPage(page);
		//setPage(applyService.findPage(search, getCurrentPage(), getPageSize()));
		return "billApplyEdit";
	}
	
	//发票-详情
	@Action("billView")
	public String billView(){
		bill=billService.find(entity.getId());
		BillApply apply=bill.getBillApply();
		
		Date d=apply.getApplyDate();
		if(d==null)
			d=apply.getCreatedAt();
		bill.setOptions(optionService.findOptionsByApply(bill.getBillApply().getId(),bill.getShop().getId()));
		//查询看是否有当前月份被之前预收的。也作显示
		List<BillOption> options=applyService.findCurrentMonthAdvance(bill.getShop().getId(),DateUtil.formatDate(d, "yyyy-MM"));
		if(bill.getOptions()!=null&&options!=null){
			for(BillOption bo:options){
				if(!bill.getOptions().contains(bo)){
					bo.setOperate(2);
					bill.getOptions().add(bo);
				}
				
			}
		}
		
		return "billView";
	}
	
	//发票-详情(用作显示关联的其它发票)
		@Action("billDisplay")
		public String billDisplay(){
			BillOption option=optionService.find(id);
			if(option!=null&&option.getBills()!=null&&option.getBills().size()>0){
				
				bill=option.getBills().get(0);
				BillApply apply=bill.getBillApply();
				Date d=apply.getApplyDate();
				if(d==null)
					d=apply.getCreatedAt();
				Long shopFianlId = 0L;
				if(bill.getShop() != null){
					shopFianlId = bill.getShop().getId();
				}else{
					shopFianlId = bill.getFinancial().getId();
				}
				bill.setOptions(optionService.findOptionsByApply(bill.getBillApply().getId(),shopFianlId));
				//查询看是否有当前月份被之前预收的。也作显示
				List<BillOption> options=applyService.findCurrentMonthAdvance(shopFianlId,DateUtil.formatDate(d, "yyyy-MM"));
				if(bill.getOptions()!=null&&options!=null){
					for(BillOption bo:options){
						if(!bill.getOptions().contains(bo)){
							bill.getOptions().add(bo);
						}
						
					}
				}
			}
			
			
			return "billDisplay";
		}
		
	//发票-保存
	@Action("billUpdate")
	public String billUpdate(){
		Bill b=billService.update(bill.getId(), editData, newData);
		
		setSuccessPopMessage("保存成功");
//		setRedirectUrl("edit.do?id="+b.getBillApply().getId());
		return SHOW_MSG_PAGE;
	}

	//发票-删除
		@Action(DELETE)
		public String delete(){
			
			applyService.delete(id);
			setSuccessPopMessage("管理费申请 删除成功");
			setRedirectUrl("index.do?currentPage="+getCurrentPage(),null,search);
			return SHOW_MSG_PAGE;
			
		}
	
	/** 统计一个发票申请 所包含的金额总和*/
	public Double getSumAmount(Long id){
		BillApply tmp= applyService.find(id);
		BigDecimal big=new BigDecimal(0D);
		for(Bill bill:tmp.getBills()){
			big=big.add(new BigDecimal(bill.getReceivableAmount()));
		}
		return big.doubleValue();
	}
	
	/**
	 * 获得预收的下一个月
	 * @return
	 * @throws Exception
	 */
	@Action("findNextMonth")
    public String findNextMonth() throws Exception {  
        List<String> monthList=applyService.findAdvanceMonths(financialId, shopId);
        if(CommonUtil.isNotEmpty(months)){
        	String ary[]=months.split(",");
        	for(String m:ary){
        		monthList.add(m);
        	}
        }
        String m=getNextMonth(monthList);
        Treaty t=treatyService.find(financialId, shopId);
        Double d=0D;
        if(t!=null)
        	d=t.getFloors();
        setJsonMsg("", true, d+"_"+m);
          
        return JSON_PAGE;  
    }
	
	/**
	 * 获得并添加季度/半年的预收月份
	 * @return
	 * @throws Exception
	 */
	@Action("addAdvanceMonth")
	public String addAdvanceMonth() throws Exception {
		bill=billService.find(entity.getId());
		StringBuilder rus=new StringBuilder();
		Treaty treaty=treatyService.find(financialId, shopId);
		String mons[]=applyService.getShMonths(treaty);
		Double d=0D;
		if(treaty!=null)
			d=treaty.getFloors();
		if("1".equals(type)){//季度
			if(mons.length<3){
				//返回错误
				rus.append(0);//可收取月份不足3个月
			}else{
				//获得随机数，保存数据库
				UUID uuid = UUID.randomUUID();
				String group=uuid.toString().replaceAll("-", "");
				String data=billService.addOptions(group,bill, treaty, mons[0],mons[1],mons[2]);
				rus.append(data);
				rus.append("|").append(d);
				rus.append("|").append(group);
			}
		}else if("2".equals(type)){//半年
			if(mons.length<6){
				//返回错误
				rus.append(0);//可收取月份不足6个月
			}else{
				//获得随机数，保存数据库
				UUID uuid = UUID.randomUUID();
				String group=uuid.toString().replaceAll("-", "");
				String data=billService.addOptions(group,bill, treaty, mons[0],mons[1],mons[2],mons[3],mons[4],mons[5]);
				rus.append(data);
				rus.append("|").append(d);
				rus.append("|").append(group);
			}
		}
		setJsonMsg("", true, rus.toString());
		
		return JSON_PAGE;  
	}
	
	/**
	 * Ajax检查月份是否重复
	 * @return
	 * @throws Exception
	 */
	@Action("checkMonth")
	public String checkMonth() throws Exception {  
		int count=applyService.checkMonth(financialId, shopId,months);
		setJsonMsg("", count>0?true:false, null);
		
		return JSON_PAGE;  
	}
	
	/**
	 * 删除发票明细
	 * @return
	 * @throws Exception
	 */
	@Action("delBillOption")
	public String delBillOption() throws Exception {  
		// months=financialId=shopId="";
		applyService.delBillOption(id);
		setJsonMsg("", true, null);
		
		return JSON_PAGE;  
	}
	
	/**
	 * 删除发票明细 (季度、半年根据组ID删除)
	 * @return
	 * @throws Exception
	 */
	@Action("delBillOptionByGroup")
	public String delBillOptionByGroup() throws Exception {
		
		applyService.delBillOptionByGroup(group);
		setJsonMsg("", true, null);
		
		return JSON_PAGE;  
	}
	
	private String getNextMonth(List<String>list) throws ParseException{
		if(list==null||list.size()==0){
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM");
			return DateUtil.getNextMonth(sdf.format(new Date()));
		}
		List<String> l=new ArrayList<String>(new LinkedHashSet<String>(list));
		Collections.sort(l);
		
		String rus=null,tmp=null;
		int length=l.size();
		for(int i=0;i<length;i++){
			if(i==length-1)
				rus=DateUtil.getNextMonth(l.get(i));
			else{
				tmp=DateUtil.getNextMonth(l.get(i));
				if(tmp.equals(l.get(i+1)))
					continue;
				else{
					rus=tmp;
					break;
				}
					
			}
		}
		return rus;
	}
	
	@Action("selectAdvanceShop")
	public String selectAdvanceShop(){
			setPage(shopService.findAdvanceShop(shopDTO,getCurrentPage(), getPageSize()));
		return "selectAdvanceShop";
	}
	
	//获得区域经理
	public String getAreaManagerNames(long billId){
		Bill bill=billService.find(billId);
		if(bill!=null&&bill.getShop()!=null){
			return getShopUserName(bill.getShop().getId());
		}
		return "";
	}
	
	//获得驻店员
	public String getShopUserNames(Long billId){
		Bill bill=billService.find(billId);
		if(bill!=null&&bill.getShop()!=null){
			return findUserShopByShopId(bill.getShop().getId());
		}
		return "";
	}
	
	public BillApply getEntity() {
		return entity;
	}

	public void setEntity(BillApply entity) {
		this.entity = entity;
	}

	public BillApply getSearch() {
		return search;
	}

	public void setSearch(BillApply search) {
		this.search = search;
	}

	public List<Object[]> getDetailData() {
		return detailData;
	}

	public void setDetailData(List<Object[]> detailData) {
		this.detailData = detailData;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Bill getBill() {
		return bill;
	}

	public void setBill(Bill bill) {
		this.bill = bill;
	}

	public List<Financial> getFinancials() {
		return financials;
	}

	public void setFinancials(List<Financial> financials) {
		this.financials = financials;
	}

	public String getMonths() {
		return months;
	}

	public void setMonths(String months) {
		this.months = months;
	}

	public Long getShopId() {
		return shopId;
	}

	public void setShopId(Long shopId) {
		this.shopId = shopId;
	}

	public Long getFinancialId() {
		return financialId;
	}

	public void setFinancialId(Long financialId) {
		this.financialId = financialId;
	}

	public String getEditData() {
		return editData;
	}

	public void setEditData(String editData) {
		this.editData = editData;
	}

	public String getNewData() {
		return newData;
	}

	public void setNewData(String newData) {
		this.newData = newData;
	}

	public int getOperate() {
		return operate;
	}

	public void setOperate(int operate) {
		this.operate = operate;
	}

	public String getIds() {
		return ids;
	}

	public void setIds(String ids) {
		this.ids = ids;
	}

	public Shop getShopDTO() {
		return shopDTO;
	}

	public void setShopDTO(Shop shopDTO) {
		this.shopDTO = shopDTO;
	}

	public String getIdmons() {
		return idmons;
	}

	public void setIdmons(String idmons) {
		this.idmons = idmons;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public List<Financial> getFinancialsQuarter() {
		return financialsQuarter;
	}

	public void setFinancialsQuarter(List<Financial> financialsQuarter) {
		this.financialsQuarter = financialsQuarter;
	}

	public List<Financial> getFinancialsHalfYear() {
		return financialsHalfYear;
	}

	public void setFinancialsHalfYear(List<Financial> financialsHalfYear) {
		this.financialsHalfYear = financialsHalfYear;
	}

	public String getGroup() {
		return group;
	}

	public void setGroup(String group) {
		this.group = group;
	}

}
